﻿//统一文件为utf-8编码编译
#pragma execution_character_set("utf-8")
///////////////////////////////////////////////////////////////////////////
// 文件名:     progressmanage.cpp
// 描述:
// 作者:      颜磊
// 创建时间:   2024-06-08 23:46
///////////////////////////////////////////////////////////////////////////
#include "progressmanage.h"
#include "QDebug"
#include "comutil.h"

#include "Userenv.h"
#include "WtsApi32.h"
#include "tchar.h"
#include "comutil.h"
#pragma comment(lib,"comsuppw.lib")
#include <QDebug>

ProgressManage::ProgressManage()
{
    //    processor_count = -1;
    //    last_time = 0;
    //    last_system_time = 0;
}

void wchar_to_string(string& szDst, wchar_t *wchar)
{
    //    wchar_t * wText = wchar;
    //    DWORD dwNum = WideCharToMultiByte(CP_ACP,NULL,wText,-1,NULL,0,NULL,FALSE);// WideCharToMultiByte的运用
    //    char *psText; // psText为char*的临时数组，作为赋值给std::string的中间变量
    //    psText = new char[dwNum];
    //    WideCharToMultiByte (CP_ACP,NULL,wText,-1,psText,dwNum,NULL,FALSE);// WideCharToMultiByte的再次运用
    //    szDst = psText;// std::string赋值
    //    delete []psText;// psText的清除

    //第一次调用确认转换后单字节字符串的长度，用于开辟空间
    int pSize = WideCharToMultiByte(CP_ACP, 0, wchar, wcslen(wchar), NULL, 0, NULL, NULL);
    char* pCStrKey = new char[pSize+1];
    //第二次调用将双字节字符串转换成单字节字符串
    WideCharToMultiByte(CP_ACP, 0, wchar, wcslen(wchar), pCStrKey, pSize, NULL, NULL);
    pCStrKey[pSize] = '\0';
    szDst = pCStrKey;
}

LPCWSTR string_to_wchar(string str)
{
    //string 转 char*
    char* pCStrKey = (char*)str.c_str();
    //第一次调用返回转换后的字符串长度，用于确认为wchar_t*开辟多大的内存空间
    int pSize = MultiByteToWideChar(CP_ACP, 0, pCStrKey, strlen(pCStrKey) + 1, NULL, 0);
    wchar_t *pWCStrKey = new wchar_t[pSize];
    //第二次调用将单字节字符串转换成双字节字符串
    int result = MultiByteToWideChar(CP_ACP, 0, pCStrKey, strlen(pCStrKey) + 1, pWCStrKey, pSize);
    return pWCStrKey;
}

LPCWSTR string2LPCWSTR(string str)
{
    //第一次调用返回转换后的字符串长度，用于确认为wchar_t*开辟多大的内存空间
    int len = MultiByteToWideChar(CP_OEMCP, 0, str.c_str(), -1, NULL, 0);
    wchar_t *buffer = new wchar_t[len + 1];
    memset(buffer,0,(len + 1) * sizeof(wchar_t));
    //第二次调用将单字节字符串转换成双字节字符串
    int result = MultiByteToWideChar(CP_OEMCP, 0, str.c_str(), str.length(), (LPWSTR)buffer, len);
    return buffer;
}


wstring string_to_wstring(string str){
    wstring result;
    int len = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.size(), NULL, 0);
    wchar_t *buffer = new wchar_t[len + 1];
    memset(buffer,0,(len + 1) * sizeof(wchar_t));
    MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.size(), buffer, len);
    result.append(buffer);
    delete [] buffer;
    return result;
}

string wstring_to_string(wstring wstr){
    string result;
    int len = WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), wstr.size(), NULL, 0,NULL,NULL);
    char *buffer = new char[len + 1];
    memset(buffer,0,(len + 1) * sizeof(char));
    WideCharToMultiByte(CP_ACP, 0, wstr.c_str(), wstr.size(), buffer, len,NULL,NULL);
    result.append(buffer);
    delete [] buffer;
    return result;
}

string ws2s(const wstring &ws){
    _bstr_t t= ws.c_str();
    char* pchar = (char*)t;
    string result = pchar;
    return result;
}

wstring s2ws(const string &s){
    _bstr_t t= s.c_str();
    wchar_t* pchar = (wchar_t*)t;
    wstring result = pchar;
    return result;
}


string TCHAR2STRING(TCHAR* str)
{
    std::string strstr;
    try
    {
        int iLen = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);

        char* chRtn = new char[iLen * sizeof(char)];

        WideCharToMultiByte(CP_UTF8, 0, str, -1, chRtn, iLen, NULL, NULL);

        strstr = chRtn;
    }
    catch (std::exception e)
    {
    }

    return strstr;
}

/// 时间转换
static uint64_t convert_time_format(const FILETIME* ftime)
{
    LARGE_INTEGER li;

    li.LowPart = ftime->dwLowDateTime;
    li.HighPart = ftime->dwHighDateTime;
    return li.QuadPart;
}

/// 获得CPU的核数
static int get_processor_number()
{
    SYSTEM_INFO info;
    GetSystemInfo(&info);
    return (int)info.dwNumberOfProcessors;
}

bool ProgressManage::checkProcessByName(string &strExe)
{
    bool bResult = false;
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (INVALID_HANDLE_VALUE == hSnapshot) {
        return NULL;
    }
    PROCESSENTRY32 pe = { sizeof(pe) };
    for (BOOL ret = Process32First(hSnapshot, &pe); ret; ret = Process32Next(hSnapshot, &pe)) {
        wchar_t* process_str = pe.szExeFile;
        string current_process_name;
        wchar_to_string(current_process_name, process_str);
        if (current_process_name == strExe) {
            qInfo() << "check process";
            bResult = true;
            break;
        }
    }
    CloseHandle(hSnapshot);
    return bResult;
}

bool ProgressManage::checkProcessById(DWORD &processId)
{
    bool res = false;
    // 进程ID有效（非零）
    if (0 != processId)
    {
        HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, processId);
        if (NULL == hProcess)
        {
            qInfo()<< __FUNCTION__ << "OpenProcess fail" << GetLastError();
        }
        else
        {
            DWORD dwExitCode = 0;
            BOOL bGet = GetExitCodeProcess(hProcess, &dwExitCode);
            if (bGet && (STILL_ACTIVE == dwExitCode)) // 正在运行
            {
                qInfo() << "check process";
                res = true;
            }
            else
            {
                qInfo() << "exit ProcessID:" << processId << "flag:" << bGet << "code:" << dwExitCode;
            }

            CloseHandle(hProcess);
            hProcess = NULL;
        }
    }
    else
    {
        qInfo() << "exit ProcessID invalid";
    }
    return res;
}

bool ProgressManage::getProcessIdByName(string &strExe,DWORD &processId)
{
    bool res= false;
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (INVALID_HANDLE_VALUE == hSnapshot) {
        qCritical()<< __FUNCTION__ << "CreateToolhelp32Snapshot error ";
        return res;
    }
    PROCESSENTRY32 pe = { sizeof(pe) };
    for (BOOL ret = Process32First(hSnapshot, &pe); ret; ret = Process32Next(hSnapshot, &pe)) {
        if (strcmp(_bstr_t(pe.szExeFile), strExe.c_str()) == 0) {
            processId = pe.th32ProcessID;
            res = true;
            break;
        }
    }
    CloseHandle(hSnapshot);
    return res;
}

bool ProgressManage::getWinlogonProcessId(DWORD &processId)
{
    bool res= false;
    DWORD winlogonSessionId;
    DWORD consoleSessionId = WTSGetActiveConsoleSessionId();

    double runTime = 0;
    string strExe = "winlogon.exe";
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (INVALID_HANDLE_VALUE == hSnapshot) {
        qCritical()<< __FUNCTION__ << "CreateToolhelp32Snapshot error ";
        return res;
    }
    PROCESSENTRY32 pe = { sizeof(pe)};
    bool isFrist = true;
    for (BOOL ret = Process32First(hSnapshot, &pe); ret; ret = Process32Next(hSnapshot, &pe)) {
        if (strcmp(_bstr_t(pe.szExeFile), strExe.c_str()) == 0) {
            DWORD curId = pe.th32ProcessID;
            uint64_t curTime;
            getProcessTimeById(curId,curTime);
//            if(isFrist){
//                runTime = curTime;
//                winlogonPid = curId;
//                isFrist = false;
//            }else{
//                if(curTime < runTime){
//                    runTime = curTime;
//                    winlogonPid = curId;
//                }
//            }
            //=========================== 方法2
//            if(curId > winlogonPid){
//                runTime = curTime;
//                winlogonPid = curId;
//            }
            //======================== 方法3
            DWORD processIdToSessionId = 0;
            ProcessIdToSessionId(pe.th32ProcessID, &processIdToSessionId);
            if(isFrist && processIdToSessionId == consoleSessionId){
                qDebug() << "是第一次，且属于控制台的winlogon";
                processId = pe.th32ProcessID;
                winlogonSessionId = consoleSessionId;
                isFrist = false;
            }
            else{
                qDebug() << "是第一次第一次，不是控制台的winlogon";
                processId = pe.th32ProcessID;
                winlogonSessionId = processIdToSessionId;
                isFrist = false;
            }
            res = true;
        }
    }
    CloseHandle(hSnapshot);
    return res;
}

BOOL DosPathToNtPath(LPTSTR pszDosPath, LPTSTR pszNtPath)
{

    TCHAR szDriveStrings[MAX_PATH] = { 0 };
    TCHAR szDosBuf[MAX_PATH] = { 0 };
    TCHAR szResultBuf[MAX_PATH] = { 0 };
    LPTSTR pDriveStr = NULL;

    // 获取盘符名到缓冲
    if (::GetLogicalDriveStrings(_countof(szDriveStrings), szDriveStrings))
    {
        // 遍历盘符名
        for (int i = 0; i < _countof(szDriveStrings); i += 4)
        {
            pDriveStr = &szDriveStrings[i];
            pDriveStr[2] = _T('\0');

            // 查询盘符对应的DOS设备名称
            if (!::QueryDosDevice(pDriveStr, szDosBuf, _countof(szDosBuf)))
            {
                break;
            }

            // 对比路径前缀
            size_t nLen = _tcslen(szDosBuf);
            if (0 == _tcsnicmp(pszDosPath, szDosBuf, nLen))
            {
                lstrcpy(pszNtPath, pDriveStr);
                lstrcat(pszNtPath, pszDosPath + nLen);
                return TRUE;
            }
        }
    }

    return FALSE;
}

/**
 * @brief enableDebugPriv 提升权限函数
 */
void ProgressManage::enableDebugPriv()
{
    HANDLE hToken;
    LUID sedebugnameValue;
    TOKEN_PRIVILEGES tkp;

    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
    {
        return;
    }

    if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue))
    {
        CloseHandle(hToken);
        return;
    }
    tkp.PrivilegeCount = 1;
    tkp.Privileges[0].Luid = sedebugnameValue;
    tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof tkp, NULL, NULL))
    {
        CloseHandle(hToken);
        return;
    }
}

// 获取进程全路径
BOOL GetProcessFullPath(DWORD dwPID,string &fullPath){
    TCHAR		szImagePath[MAX_PATH];
    TCHAR		pszFullPath[MAX_PATH];
    HANDLE		hProcess;

    // 初始化失败
    if(!pszFullPath){return FALSE;}
    pszFullPath[0] = '\0';

    // 获取进程句柄失败
    hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, 0, dwPID);
    if(!hProcess){
        qCritical() << "OpenProcess error";
        return FALSE;
    }

    // 获取进程完整路径失败
    if(!GetProcessImageFileName(
                hProcess,					// 进程句柄
                szImagePath,				// 接收进程所属文件全路径的指针
                MAX_PATH					// 缓冲区大小
                )){
        qCritical() << "GetProcessImageFileName error";
        CloseHandle(hProcess);
        return FALSE;
    }

    // qDebug() <<  "dosPath" << szImagePath;
    // 路径转换失败
    if(!DosPathToNtPath(szImagePath, pszFullPath)){
        CloseHandle(hProcess);
        qCritical() <<  "DosPathToNtPath error" ;
        return FALSE;
    }

    CloseHandle(hProcess);

    // 导出文件全路径
    fullPath = TCHAR2STRING(pszFullPath);

    return TRUE;
}

bool ProgressManage::getProcessIdByPath(string &proPath,DWORD &processId)
{
    bool res = false;
    string::size_type iPos = proPath.find_last_of('/') + 1;
    string filename = proPath.substr(iPos, proPath.length() - iPos);
    //2.获取不带后缀的文件名
    //string name = filename.substr(0, filename.rfind("."));
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (INVALID_HANDLE_VALUE == hSnapshot) {
        qCritical() << "CreateToolhelp32Snapshot error ";
        return res;
    }
    PROCESSENTRY32 pe = { sizeof(pe) };
    for (BOOL ret = Process32First(hSnapshot, &pe); ret; ret = Process32Next(hSnapshot, &pe)) {
        if (strcmp(_bstr_t(pe.szExeFile), filename.c_str()) == 0) {
            string getPath;
            GetProcessFullPath(pe.th32ProcessID,getPath);
            replace(getPath.begin(),getPath.end(),'\\','/');
            //qDebug() << __FUNCTION__ << proPath.c_str() << getPath.c_str() << pe.th32ProcessID;
            if(proPath == getPath){
                CloseHandle(hSnapshot);
                processId = pe.th32ProcessID;
                res = true;
            }
        }
    }
    CloseHandle(hSnapshot);
    return res;
}

list<DWORD> ProgressManage::getProcessIdsByPath(string &proPath)
{
    list<DWORD> pIds;
    string::size_type iPos = proPath.find_last_of('/') + 1;
    string filename = proPath.substr(iPos, proPath.length() - iPos);
    //2.获取不带后缀的文件名
    //string name = filename.substr(0, filename.rfind("."));
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (INVALID_HANDLE_VALUE != hSnapshot) {
        PROCESSENTRY32 pe = { sizeof(pe) };
        for (BOOL ret = Process32First(hSnapshot, &pe); ret; ret = Process32Next(hSnapshot, &pe)) {
            if (strcmp(_bstr_t(pe.szExeFile), filename.c_str()) == 0) {
                string getPath;
                GetProcessFullPath(pe.th32ProcessID,getPath);
                replace(getPath.begin(),getPath.end(),'\\','/');
                if(proPath == getPath ){
                    pIds.push_back(pe.th32ProcessID);
                }
            }
        }
    }else{
        qCritical() << __FUNCTION__ << "CreateToolhelp32Snapshot error";
    }
    CloseHandle(hSnapshot);
    return pIds;
}

string ProgressManage::getProcessNameById(DWORD &processId)
{
    string res = "";
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (INVALID_HANDLE_VALUE == hSnapshot) {
        qInfo() << "getProcessNameById error ";
        return res;
    }
    PROCESSENTRY32 pe = { sizeof(pe) };
    for (BOOL ret = Process32First(hSnapshot, &pe); ret; ret = Process32Next(hSnapshot, &pe)) {
        if (pe.th32ProcessID == processId) {

            CloseHandle(hSnapshot);
            qInfo() << "getProcessNameById: " << pe.szExeFile;
            wchar_to_string(res,pe.szExeFile);
            break;
        }
    }
    CloseHandle(hSnapshot);
    return res;
}


int64_t systemtime_to_time_t(SYSTEMTIME &st){
    tm localTm = {st.wSecond,st.wMinute,st.wHour,st.wDay,st.wMonth - 1,st.wYear - 1900,st.wDayOfWeek,0,0};
    //    localTm.tm_year = st.wYear - 1900;
    //    localTm.tm_mon = st.wMonth - 1;
    //    localTm.tm_mday = st.wDay;
    //    localTm.tm_hour = st.wHour;
    //    localTm.tm_min = st.wMinute;
    //    localTm.tm_sec = st.wSecond;
    //    localTm.tm_yday = 0;
    //    localTm.tm_isdst = 0;
    //    qCritical()<< __FUNCTION__ << localTm.tm_year << localTm.tm_mon << localTm.tm_mday << localTm.tm_hour << localTm.tm_min << localTm.tm_sec;
    time_t timeT = mktime(&localTm);
    //    timeT *= 1000;
    //    timeT += st.wMilliseconds;

    return  timeT;
}

SYSTEMTIME time_t_to_systemtime(time_t t){
    tm temptm = *localtime(&t);
    SYSTEMTIME st = {WORD(1900 + temptm.tm_year),
                     WORD(1 + temptm.tm_mon),
                     WORD(temptm.tm_wday),
                     WORD(temptm.tm_mday),
                     WORD(temptm.tm_hour),
                     WORD(temptm.tm_min),
                     WORD(temptm.tm_sec),
                     WORD(0)};
    return st;
};
bool ProgressManage::getProcessTimeById(DWORD &processId, uint64_t &time)
{
    bool res = false;
    HANDLE hProcess = NULL;
    //打开目标进程
    hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION,FALSE, processId);
    if (hProcess == NULL) {
        qCritical()<< __FUNCTION__ << "OpenProcess failed"<< GetLastError();
        return res;
    }

    FILETIME creationTime,exitTime,kernelTime,userTime;
    if(GetProcessTimes(hProcess,&creationTime,&exitTime,&kernelTime,&userTime)){
        FILETIME localFileTime;
        FileTimeToLocalFileTime(&creationTime,&localFileTime);

        SYSTEMTIME localSystemTime;;
        FileTimeToSystemTime(&localFileTime,&localSystemTime);

        SYSTEMTIME nowLocalSystemTime;
        GetLocalTime(&nowLocalSystemTime);

        int64_t now_time_t =systemtime_to_time_t(nowLocalSystemTime) - systemtime_to_time_t(localSystemTime);

        //time = (double)now_time_t / 1000.0;
        time = now_time_t;
        res = true;
    }else{
        qCritical()<< __FUNCTION__ << "GetProcessTimes failed"<< GetLastError();
    }
    CloseHandle(hProcess);
    return res;
}

void ProgressManage::killProcessById(DWORD &processId)
{
    HANDLE hProcess = NULL;
    //打开目标进程
    hProcess = OpenProcess(PROCESS_TERMINATE,FALSE, processId);
    if (hProcess == NULL) {
        qCritical()<< __FUNCTION__ << "Open Process failed"<< GetLastError();
        return;
    }
    //结束目标进程
    //    DWORD ret=TerminateProcess(hProcess,0);
    //    if(ret == 0) {
    //        qInfo()<<"error ：kill task failed" << GetLastError();
    //        return;
    //    }
    //挂起的进程上面无法结束
    system(QString("taskkill /f /t /pid %1").arg(processId).toStdString().c_str());
    //taskkill [/S system [/U username [/P [password]]]] { [/FI filter] [/PID processid | /IM imagename] } [/T] [/F]
    //参数:
    //    /S system 远程计算机名
    //    /U  用户名
    //    /P 密码, /S /U /P 参数一起使用
    //    /PID processid 要杀死进程的 PID 号
    //    /IM imagename 根据镜像名字来查杀进程
    //    /F 强制结束进程
    //    /T 杀死和 PID 或镜像名有关的进程
    //    /FI filter 筛选器, 批量杀死进程
}

bool ProgressManage::get_cpu_usage(DWORD &processId,float &cpu_usage)
{
    bool bResult = false;
    // 进程ID有效（非零）
    if (0 != processId)
    {
        //PROCESS_QUERY_INFORMATION   //获得进程信息的权限，如它的退出代码、优先级
        //PROCESS_QUERY_LIMITED_INFORMATION  /*获得某些信息的权限，如果获得了PROCESS_QUERY_INFORMATION，也拥有PROCESS_QUERY_LIMITED_INFORMATION权限*/
        HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION  , FALSE, processId);
        if (NULL == hProcess)
        {
            qCritical()<< __FUNCTION__ << "OpenProcess fail" << GetLastError();
        }
        else
        {
            FILETIME now;
            FILETIME creation_time;
            FILETIME exit_time;
            FILETIME kernel_time;
            FILETIME user_time;
            int64_t system_time;
            int64_t time;
            int64_t system_time_delta;
            int64_t time_delta;

            if(lastTimeMap.find(processId) == lastTimeMap.end()){
                LastTime lastTime;
                lastTime.last_system_time=0;
                lastTime.last_time=0;
                lastTimeMap[processId] = lastTime;
            }

            // get cpu num
            SYSTEM_INFO info;
            GetSystemInfo(&info);
            int cpu_num = info.dwNumberOfProcessors;

            GetSystemTimeAsFileTime(&now);
            if (!GetProcessTimes(hProcess, &creation_time, &exit_time, &kernel_time, &user_time))
            {
                // We don't assert here because in some cases (such as in the Task Manager)
                // we may call this function on a process that has just exited but we have
                // not yet received the notification.
                printf("GetCpuUsageRatio GetProcessTimes failed\n");
            }else{
                // should handle the multiple cpu num
                system_time = (convert_time_format(&kernel_time) + convert_time_format(&user_time)) / cpu_num;
                time = convert_time_format(&now);

                if ((lastTimeMap[processId].last_system_time == 0) || (lastTimeMap[processId].last_time == 0)){
                    // First call, just set the last values.
                    lastTimeMap[processId].last_system_time = system_time;
                    lastTimeMap[processId].last_time = time;
                    //qDebug() << lastTimeMap[processId].last_system_time << lastTimeMap[processId].last_time;
                    Sleep(1000);
                    bResult = get_cpu_usage(processId,cpu_usage);
                }else{
                    system_time_delta = system_time - lastTimeMap[processId].last_system_time;
                    time_delta = time - lastTimeMap[processId].last_time;

                    //qDebug() << system_time << lastTimeMap[processId].last_system_time << time << lastTimeMap[processId].last_time << system_time_delta << time_delta << cpu_num;

                    if (time_delta != 0)
                    {
                        // We add time_delta / 2 so the result is rounded.
                        cpu_usage = ((float)(system_time_delta * 100) / (float)time_delta); // the % unit
                        lastTimeMap[processId].last_system_time = system_time;
                        lastTimeMap[processId].last_time = time;
                        bResult = true;
                    }
                }
            }
            CloseHandle(hProcess);
            hProcess = NULL;
        }
    }
    else
    {
        qCritical() << "exit ProcessID invalid";
    }
    return bResult;
}

bool ProgressManage::get_memory_usage(DWORD &processId, uint64_t &mem, uint64_t &vmem)
{
    bool bResult = false;
    // 进程ID有效（非零）
    if (0 != processId)
    {
        HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processId);
        if (NULL == hProcess)
        {
            qCritical() << __FUNCTION__  << "OpenProcess fail" << GetLastError();
        }
        else
        {
            PROCESS_MEMORY_COUNTERS pmc;
            if(GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc)))
            {
                mem = pmc.WorkingSetSize;
                vmem = pmc.PagefileUsage;
                bResult = true;
            }
            CloseHandle(hProcess);
            hProcess = NULL;
        }
    }
    else
    {
        qCritical() << "exit ProcessID invalid";
    }
    return bResult;
}

bool ProgressManage::get_io_bytes(DWORD &processId, uint64_t &read_bytes, uint64_t &write_bytes)
{
    bool bResult = false;
    // 进程ID有效（非零）
    if (0 != processId)
    {
        HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processId);
        if (NULL == hProcess)
        {
            qCritical() << __FUNCTION__ << processId << "OpenProcess fail" << GetLastError();
        }
        else
        {
            IO_COUNTERS io_counter;
            if(GetProcessIoCounters(GetCurrentProcess(), &io_counter))
            {
                read_bytes = io_counter.ReadTransferCount;
                write_bytes = io_counter.WriteTransferCount;
                bResult = true;
            }
            CloseHandle(hProcess);
            hProcess = NULL;
        }
    }
    else
    {
        qInfo() << "exit ProcessID invalid";
    }
    return bResult;
}



bool ProgressManage::ServerRunWndProcess(LPWSTR lpExePath)
{
    HANDLE hToken = NULL;

    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken))
    {
        return false;
    }

    HANDLE hTokenDup = NULL;
    bool bRet = DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, NULL, SecurityIdentification, TokenPrimary, &hTokenDup);
    if (!bRet || hTokenDup == NULL)
    {
        CloseHandle(hToken);
        return false;
    }

    DWORD dwSessionId = WTSGetActiveConsoleSessionId();
    //把服务hToken的SessionId替换成当前活动的Session(即替换到可与用户交互的winsta0下)
    if (!SetTokenInformation(hTokenDup, TokenSessionId, &dwSessionId, sizeof(DWORD)))
    {
        DWORD nErr = GetLastError();
        CloseHandle(hTokenDup);
        CloseHandle(hToken);
        return false;
    }

    STARTUPINFO si;
    ZeroMemory(&si, sizeof(STARTUPINFO));

    si.cb = sizeof(STARTUPINFO);
    //si.lpDesktop = _T("WinSta0\\Default");
    wchar_t desktopName[] = TEXT("winsta0\\default");
    si.lpDesktop = (wchar_t*)desktopName;
    si.wShowWindow = SW_SHOW;
    si.dwFlags = STARTF_USESHOWWINDOW /*|STARTF_USESTDHANDLES*/;

    //=======================创建进程环境块
    LPVOID pEnv = NULL;
    bRet = CreateEnvironmentBlock(&pEnv, hTokenDup, FALSE);
    if (!bRet)
    {
        CloseHandle(hTokenDup);
        CloseHandle(hToken);
        return false;
    }

    if (pEnv == NULL)
    {
        CloseHandle(hTokenDup);
        CloseHandle(hToken);
        return false;
    }

    //在活动的Session下创建进程
    PROCESS_INFORMATION processInfo;
    ZeroMemory(&processInfo, sizeof(PROCESS_INFORMATION));
    DWORD dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT;

    string proPath;
    wchar_to_string(proPath,lpExePath);
    int index = proPath.find_last_of("/");
    string filedir = proPath.substr(0, index);
    //qDebug() << "run Path" << QString::fromStdString(filedir) << QString(filedir.c_str()) << string_to_wchar(QString(filedir.c_str()).toStdString());

    if (!CreateProcessAsUser(hTokenDup, NULL, lpExePath, NULL, NULL, FALSE, dwCreationFlag, pEnv, string_to_wchar(filedir), &si, &processInfo))
    {
        DWORD nRet = GetLastError();
        CloseHandle(hTokenDup);
        CloseHandle(hToken);
        return false;
    }

    DestroyEnvironmentBlock(pEnv);
    CloseHandle(hTokenDup);
    CloseHandle(hToken);

    return true;
}

bool ProgressManage::serverCreateProcessAsAdmin(string &path)
{
    STARTUPINFO si;
    HANDLE hToken;
    HANDLE hTokenDup = NULL;

    ZeroMemory(&si, sizeof(STARTUPINFO));

    si.cb = sizeof(STARTUPINFO);
    wchar_t desktopName[] = TEXT("winsta0\\default");
    si.lpDesktop = (wchar_t*)desktopName;///加入窗口站


    DWORD dwWinlogon;
    getWinlogonProcessId(dwWinlogon);
    HANDLE hProcess = OpenProcess(MAXIMUM_ALLOWED, FALSE, dwWinlogon);
    if (hProcess == NULL)
    {
        qCritical()<<__FUNCTION__ << "OpenProcess error";
        return false;
    }

    BOOL bResult = OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY
                                    | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_SESSIONID
                                    | TOKEN_READ | TOKEN_WRITE, &hToken);
    CloseHandle(hProcess);
    if (FALSE == bResult)
    {
        qCritical()<<__FUNCTION__ << "OpenProcessToken error";
        return false;
    }

    // 创建一个新的访问令牌来复制一个已经存在的标记
    bool bRet = DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hTokenDup);
    if (!bRet || hTokenDup == NULL)
    {
        qCritical()<<__FUNCTION__ << "DuplicateTokenEx error";
        CloseHandle(hToken);
        return false;
    }

    //=======================创建进程环境块
    LPVOID pEnv = NULL;
    bRet = CreateEnvironmentBlock(&pEnv, hTokenDup, FALSE);
    if (!bRet)
    {
        qCritical()<<__FUNCTION__ << "CreateEnvironmentBlock error";
        CloseHandle(hTokenDup);
        CloseHandle(hToken);
        return false;
    }

    if (pEnv == NULL)
    {
        CloseHandle(hTokenDup);
        CloseHandle(hToken);
        return false;
    }

    //在活动的Session下创建进程
    PROCESS_INFORMATION pi;
    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
    DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT;

    int index = path.find_last_of("/");
    string filedir = path.substr(0, index);
    // 通过winlogon创建一个进程
    if (!CreateProcessAsUser(hTokenDup, NULL,(wchar_t*)string_to_wstring(path).c_str(), NULL, NULL, FALSE, dwCreationFlags, pEnv,(wchar_t*)string_to_wstring(filedir).c_str(), &si, &pi))
    {
        qCritical()<<__FUNCTION__ << "CreateProcessAsUser error";
        DWORD nRet = GetLastError();
        DestroyEnvironmentBlock(pEnv);
        CloseHandle(hTokenDup);
        CloseHandle(hToken);
        return false;
    }

    DestroyEnvironmentBlock(pEnv);
    CloseHandle(hTokenDup);
    CloseHandle(hToken);
    return true;
}

bool ProgressManage::serverCreateProcessAsAdmin2(string &path)
{
    int index = path.find_last_of("/");
    string filedir = path.substr(0, index);

    PROCESS_INFORMATION pi;
    STARTUPINFO si;
    BOOL bResult = FALSE;
    DWORD consoleSessionId,winlogonSessionId,winlogonPid;
    HANDLE hUserToken=INVALID_HANDLE_VALUE,hUserTokenDup=INVALID_HANDLE_VALUE,
            hPToken=INVALID_HANDLE_VALUE,hProcess=INVALID_HANDLE_VALUE;
    DWORD dwCreationFlags;

    int errorcode;//whl2023-10-18
    LPVOID pEnv =NULL;

    // 将客户端登录到本地计算机
    consoleSessionId = WTSGetActiveConsoleSessionId();

    //添加Sessionid用原始会话的sessionId
    {
        //==============================
        //    PWTS_SESSION_INFO psi;
        //    DWORD dwCount;

        //    qDebug() << QString("WTSGetActiveConsoleSessionId:%1").arg(hid);
        //    printf("WTSGetActiveConsoleSessionId: %d \n", hid);
        //    BOOL bRet = ;

        //    if (WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &psi, &dwCount)){
        //        std::wstring strName;
        //        for (unsigned int i = 0; i < dwCount; i ++)
        //        {
        //            if( wstring_to_string(psi[i].pWinStationName) != "Console"){
        //                consoleSessionId = psi[i].SessionId;
        //                qDebug() << "consoleSessionId:" << wstring_to_string(psi[i].pWinStationName).c_str() << psi[i].SessionId;
        //                break;
        //            }
        //            qDebug()<< psi[i].SessionId << "pWinStationName: "<<QString::fromStdWString(psi[i].pWinStationName);
        //            qDebug() << "SessionId:"<< psi[i].SessionId;
        //            qDebug() << "State:"<< psi[i].State;

        //            consoleSessionId = psi[i].SessionId;
        //            PVOID pstr = NULL;
        //            DWORD dwLen = 0;
        //            WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, consoleSessionId, WTS_INFO_CLASS::WTSUserName, (LPWSTR*)&pstr, &dwLen);

        //            std::wstring strUserName = (PWCHAR)pstr;
        //            qDebug() << "strUserName:  "<<QString::fromStdWString(strUserName);
        //printf("strUserName:%s \n", strUserName.c_str());

        //        }
        //        WTSFreeMemory(psi);
        //    }
    }
    //===============================
    // Find the winlogon process
    PROCESSENTRY32 procEntry;

    HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hSnap == INVALID_HANDLE_VALUE)
    {
        return false ;
    }

    procEntry.dwSize = sizeof(PROCESSENTRY32);

    if (!Process32First(hSnap, &procEntry))
    {
        return false ;
    }

    bool isFrist = true;
    do
    {
        if (_wcsicmp(procEntry.szExeFile, L"winlogon.exe") == 0)
        {
            DWORD processIdToSessionId = 0;
            ProcessIdToSessionId(procEntry.th32ProcessID, &processIdToSessionId);
            if(isFrist && processIdToSessionId == consoleSessionId){
                qDebug() << "是第一次，且属于控制台的winlogon";
                winlogonPid = procEntry.th32ProcessID;
                winlogonSessionId = consoleSessionId;
                isFrist = false;
            }
            else{
                qDebug() << "是第一次第一次，不是控制台的winlogon";
                winlogonPid = procEntry.th32ProcessID;
                winlogonSessionId = processIdToSessionId;
                isFrist = false;
            }
        }
    } while (Process32Next(hSnap, &procEntry));


    //    if(!WTSQueryUserToken(consoleSessionId,&hUserToken)){
    //        qCritical() << "WTSQueryUserToken error";
    //    }
    //    if(!WTSQueryUserToken(consoleSessionId,&hUserToken)){
    //        qCritical() << "WTSQueryUserToken error";
    //    }
    dwCreationFlags = NORMAL_PRIORITY_CLASS|CREATE_NEW_CONSOLE;
    ZeroMemory(&si, sizeof(STARTUPINFO));
    si.cb= sizeof(STARTUPINFO);
    wchar_t desktopName[] = TEXT("winsta0\\default");
    si.lpDesktop = (wchar_t*)desktopName;///加入窗口站
    ZeroMemory(&pi, sizeof(pi));
    TOKEN_PRIVILEGES tp;
    LUID luid;
    hProcess = OpenProcess(MAXIMUM_ALLOWED,FALSE,winlogonPid);

    if(!::OpenProcessToken(hProcess,TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY
                           |TOKEN_DUPLICATE|TOKEN_ASSIGN_PRIMARY|TOKEN_ADJUST_SESSIONID
                           |TOKEN_READ|TOKEN_WRITE,&hPToken))
    {
        errorcode = GetLastError();
        qCritical() << "Process token open Error:" << errorcode;
        goto ToFree;
    }

    if (!LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&luid))
    {
        errorcode = GetLastError();
        qCritical() << "Lookup Privilege value Error:" << errorcode;
        goto ToFree;
    }
    tp.PrivilegeCount =1;
    tp.Privileges[0].Luid =luid;
    tp.Privileges[0].Attributes =SE_PRIVILEGE_ENABLED;

    if(!DuplicateTokenEx(hPToken,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary,&hUserTokenDup)){
        errorcode = GetLastError();
        qCritical() << "Adjust Privilege value Error:" << errorcode;
        goto ToFree;
    }

    // 调整Token权限
    //    SetTokenInformation(hUserTokenDup,TokenSessionId,(void*)consoleSessionId,sizeof(DWORD));
    SetTokenInformation(hUserTokenDup,TokenSessionId,(void*)consoleSessionId,sizeof(DWORD));

    if (!AdjustTokenPrivileges(hUserTokenDup,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),
                               (PTOKEN_PRIVILEGES)NULL,NULL))
    {
        errorcode = GetLastError();
        qCritical() << "Adjust Privilege value Error:";
        goto ToFree;
    }
    //创建进程环境快
    if(!CreateEnvironmentBlock(&pEnv,hUserTokenDup,TRUE))
    {
        errorcode = GetLastError();
        qCritical() << "CreateEnvironmentBlock error";
        goto ToFree;
    }
    else{
        dwCreationFlags|=CREATE_UNICODE_ENVIRONMENT;
    }
    // 在客户端的登录会话中启动进程
    if (CreateProcessAsUser(
                hUserTokenDup,                     // client's access token
                //_T("cmd.exe"),        // file to execute
                //NULL,                 // command line
                NULL,                   // file to execute
                (wchar_t*)string_to_wstring(path).c_str(),  // command line
                NULL,            // pointer to process SECURITY_ATTRIBUTES
                NULL,               // pointer to thread SECURITY_ATTRIBUTES
                FALSE,              // handles are not inheritable
                dwCreationFlags,     // creation flags
                pEnv,               // pointer to new environment block
                (wchar_t*)string_to_wstring(filedir).c_str(),               // name of current directory
                &si,               // pointer to STARTUPINFO structure
                &pi                // receives information about new process
                )
            ){
        bResult = true;
    }else{
        qCritical()<<__FUNCTION__ << "CreateProcessAsUser error";
        errorcode = GetLastError();
    }
    // Perform All the Close Handles tasks
ToFree:
    {
        if(hProcess != INVALID_HANDLE_VALUE)
        {
            CloseHandle(hProcess);
        }
        if(hUserToken != INVALID_HANDLE_VALUE)
        {
            CloseHandle(hUserToken);
        }
        if(hUserTokenDup != INVALID_HANDLE_VALUE)
        {
            CloseHandle(hUserTokenDup);
        }
        if(hPToken != INVALID_HANDLE_VALUE)
        {
            CloseHandle(hPToken);
        }
    }
    return bResult;
}

bool ProgressManage::appCreateProcessAsAdmin(string &path)
{
    STARTUPINFO si;
    HANDLE hToken;
    HANDLE hTokenDup = NULL;

    ZeroMemory(&si, sizeof(STARTUPINFO));

    si.cb = sizeof(STARTUPINFO);
    wchar_t desktopName[] = TEXT("winsta0\\default");
    si.lpDesktop = (wchar_t*)desktopName;///加入窗口站

    HANDLE hProcess = OpenProcess(MAXIMUM_ALLOWED, FALSE, GetCurrentProcessId());
    if (hProcess == NULL)
    {
        qCritical()<<__FUNCTION__ << "OpenProcess error";
        return false;
    }

    BOOL bResult = OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY
                                    | TOKEN_DUPLICATE | TOKEN_ASSIGN_PRIMARY | TOKEN_ADJUST_SESSIONID
                                    | TOKEN_READ | TOKEN_WRITE, &hToken);
    CloseHandle(hProcess);
    if (FALSE == bResult)
    {
        qCritical()<<__FUNCTION__ << "OpenProcessToken error";
        return false;
    }

    // 创建一个新的访问令牌来复制一个已经存在的标记
    bool bRet = DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification, TokenPrimary, &hTokenDup);
    if (!bRet || hTokenDup == NULL)
    {
        qCritical()<<__FUNCTION__ << "DuplicateTokenEx error";
        CloseHandle(hToken);
        return false;
    }

    //=======================创建进程环境块
    LPVOID pEnv = NULL;
    bRet = CreateEnvironmentBlock(&pEnv, hTokenDup, FALSE);
    if (!bRet)
    {
        qCritical()<<__FUNCTION__ << "CreateEnvironmentBlock error";
        CloseHandle(hTokenDup);
        CloseHandle(hToken);
        return false;
    }

    if (pEnv == NULL)
    {
        CloseHandle(hTokenDup);
        CloseHandle(hToken);
        return false;
    }

    //在活动的Session下创建进程
    PROCESS_INFORMATION pi;
    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
    DWORD dwCreationFlags = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT;

    int index = path.find_last_of("/");
    string filedir = path.substr(0, index);
    // 通过winlogon创建一个进程
    if (!CreateProcessAsUser(hTokenDup, NULL,(wchar_t*)string_to_wstring(path).c_str(), NULL, NULL, FALSE, dwCreationFlags, pEnv,(wchar_t*)string_to_wstring(filedir).c_str(), &si, &pi))
    {
        qCritical()<<__FUNCTION__ << "CreateProcessAsUser error";
        DWORD nRet = GetLastError();
        DestroyEnvironmentBlock(pEnv);
        CloseHandle(hTokenDup);
        CloseHandle(hToken);
        return false;
    }

    DestroyEnvironmentBlock(pEnv);
    CloseHandle(hTokenDup);
    CloseHandle(hToken);
    return true;
}


bool ProgressManage::StartProcessByPath(string &path)
{
    DWORD progressId;
    //如果查不到该进程则启动
    if(getProcessIdByPath(path,progressId)){
        //qDebug() << QString("启动进程")<< progressId << QString::fromStdString(path);
        serverCreateProcessAsAdmin(path);
    }
    return true;
}

bool ProgressManage::StopProcessByPath(string &path)
{
    DWORD progressId;
    //如果查不到该进程则启动
    if(getProcessIdByPath(path,progressId)){
        //qDebug() << QString("结束进程") << QString::fromStdString(path);
        killProcessById(progressId);
    }
    return true;
}

bool ProgressManage::appStartProcessByPath(string &path)
{
    DWORD progressId;
    //如果查不到该进程则启动
    if(!getProcessIdByPath(path,progressId)){
//        qDebug() << QString("启动进程")<< progressId << QString::fromStdString(path);
        appCreateProcessAsAdmin(path);
    }
    return true;
}

bool ProgressManage::appStopProcessByPath(string &path)
{
    DWORD progressId;
    //如果查不到该进程则启动
    if(getProcessIdByPath(path,progressId)){
        //qDebug() << QString("结束进程") << QString::fromStdString(path);
        killProcessById(progressId);
    }
    return true;
}
